#pragma once
#include<iostream>
#include"mutex.hpp"
#include<fstream>
#include <unistd.h>
#include <filesystem>
#include <stdexcept>
#include<sstream>

namespace ly{
    //默认路径
    const std::string defaultpath = "./log/";
    //默认文件名
    const std::string defaultname = "log.txt";
    // ⽇志等级 
    enum class LogLevel
    {
        DEBUG,
        INFO,
        WARNING,
        ERROR,
        FATAL
    };
    std::string LogLevelToStr(LogLevel level){
        switch(level){
            case LogLevel::DEBUG:
                return "DEBUG";
            case LogLevel::INFO:
                return "INFO";
            case LogLevel::WARNING:
                return "WARNING";
            case LogLevel::ERROR:
                return "ERROR";
            case LogLevel::FATAL:
                return "FATAL";
            default:
                return "UNKNOWN";
        }
    }
    std::string GetTime(){
        time_t now=time(0);
        tm *ltm=localtime(&now);
        char buf[64];
        strftime(buf,sizeof(buf),"%Y-%m-%d %H:%M:%S",ltm);
        return buf;
    }
    class LogStrategy{
        public:
            virtual void SyncLog(const std::string msg) = 0;
            virtual ~LogStrategy()=default;
    };
    //日志类
    //终端输出日志策略
    class LConsoleLogStrategyog:public LogStrategy{
        public:
            //构造函数
            LConsoleLogStrategyog(){
            }
            void SyncLog(std::string msg) override{
                LockGuard lock(_mutex);
                std::cout<<msg<<std::endl;
            }
        private:
            ly::Mutex _mutex; 
    };
    //文件输出日志策略
    class LFileLogStrategy:public LogStrategy{
        public:
            //构造函数
            // LFileLogStrategy(const std::string filepath=defaultpath,const std::string name=defaultname){
            //     _file=filepath+name;
            //     std::cout<<_file<<std::endl;
            //     if (std::filesystem::exists(filepath))
            //         return;
            //     try{
            //         std::filesystem::create_directories(filepath);
            //     }
            //     catch (const std::filesystem::filesystem_error &e){
            //         std::cerr << e.what() << '\n';
            //     }
            // }
            LFileLogStrategy(const std::string& filepath = defaultpath, const std::string& name = defaultname) {
                _file = filepath + name;
                try {
                    // 获取完整文件路径的目录部分
                    std::filesystem::path fullPath(_file);
                    std::filesystem::path dirPath = fullPath.parent_path();
                    
                    // 检查目录是否不存在，如果不存在则创建
                    if (!std::filesystem::exists(dirPath)) {
                        std::cout << "创建目录: " << dirPath << std::endl;
                        std::filesystem::create_directories(dirPath);
                    } else {
                        std::cout << "目录已存在: " << dirPath << std::endl;
                    }
                } catch (const std::filesystem::filesystem_error& e) {
                    std::cerr << "创建目录失败: " << e.what() << std::endl;
                }
            }
            void SyncLog(std::string msg) override{
                LockGuard lock(_mutex);
                std::ofstream ofs(_file,std::ios::app);
                ofs<<msg<<std::endl;
                ofs.close();
            }
            private:
            std::string _file;
            ly::Mutex _mutex; 
    };
    //日志类
    class Log{
        public:
            //构造函数
            Log(){
                _strategy=new LConsoleLogStrategyog();
            }
            void UseConsoleStrategy(){
                _strategy=new LConsoleLogStrategyog();
            }
            void UseFileStrategy(const std::string path=defaultpath,const std::string name=defaultname){
                _strategy=new LFileLogStrategy(path,name);
            }
            class LogMessage{
                public:
                    LogMessage(ly::LogLevel level,const std::string filename,int line,ly::Log& log):_log(log){
                        _time=GetTime();
                        _level=LogLevelToStr(level);
                        _pid=std::to_string(getpid());
                        _filename=filename;
                        _line=std::to_string(line);
                    }
                    ~LogMessage(){
                        std::string logmsg="["+_time+"]"+"["+_level+"]"+"["+_pid+"]"+"["+_filename+"]"+"["+_line+"]"+":"+_msg;
                        _log._strategy->SyncLog(logmsg);
                    }
                    template<class T>
                    LogMessage& operator<<(const T msg){
                        std::stringstream ssbuffer;
                        ssbuffer<<msg;
                        _msg+=ssbuffer.str();
                        return *this;
                    }
                    LogMessage& operator<<(const char* msg) {
                        _msg += msg;  // 直接拼接字符串，无需stringstream
                        return *this;
                    }
                private:
                    std::string _time,_level,_pid,_filename,_line,_msg;
                    ly::Log& _log;
            };
            LogMessage operator()(ly::LogLevel level ,std::string filename,int line){
                return LogMessage(level,filename,line,*this);
            }
        private:
        LogStrategy* _strategy;
    };

}
    ly::Log mylog;
    #define LOG(level) mylog(level,__FILE__,__LINE__)
    //#define LOG(level) (log(level, __FILE__, __LINE__))
    #define ENABLE_FILE_LOG_STRATEGY mylog.UseFileStrategy()
    #define ENABLE_CONSOLE_LOG_STRATEGY mylog.UseConsoleStrategy()